import time
from Autotests.LocalMachine.Pages.AirManager.DevicePage import DevicePage
from Autotests.LocalMachine.Pages.BasePage import BaseWebManagerPage
from Autotests.LocalMachine.Pages.BaseDialog import BaseWebDialog
from Autotests.LocalMachine.UiObjectsMap import AirManager
from Autotests.LocalMachine.UiObjectsMap.AirClient import Dialog
from Autotests.LocalMachine.UiObjectsMap.AirManager import MainFrame, Group
from Autotests.LocalMachine.Controls import *
from Autotests.LocalMachine.Controls.ListView import WebListViewDelegateBuilder
from Autotests.LocalMachine.Controls.BaseControl import WebFindKey
from Autotests.LocalMachine.Controls.BaseView import BaseWebViewLeafDelegate
from Autotests.LocalMachine.Controls.TableView import WebTableView, WebTableViewDelegateBuilder
from Autotests.WebDriver import DRIVER


class GroupDialog(BaseWebDialog):
    def __init__(self):
        super(GroupDialog, self).__init__()
        self._txtGroupName = WebLineEdit(Group.txtGroupName)

    def goToHomeLocation(self):
        pass

    def setGroupName(self, groupName):
        self._txtGroupName.typeText(groupName)

    def save(self):
        WebButton(Group.btnSubmit).click()

    def cancel(self):
        WebButton(Group.btnCancel).click()


class WebGroupListDelegate(BaseWebViewLeafDelegate):
    def __init__(self, handler, index):
        super(WebGroupListDelegate, self).__init__(handler, index)
        self._group = WebLabel(self.waitChildControl(*MainFrame.ListGroupItem.labelGroupName))

    def groupName(self):
        return self._group.text()

    def makeSettingsIconVisible(self):
        DRIVER().actionChains().move_to_element(self).perform()
        WebButton(self.waitChildControl(*MainFrame.ListGroupItem.btnGroupSettings)).click()
        if not BaseWebControl(self.waitChildControl(*MainFrame.ListGroupItem.menuEditDelete)).isVisible():
            DRIVER().actionChains().move_to_element(self).perform()
            WebButton(self.waitChildControl(*MainFrame.ListGroupItem.btnGroupSettings)).click()

    def showEditGroupDialog(self):
        self.makeSettingsIconVisible()
        WebButton(self.waitChildControl(*MainFrame.ListGroupItem.btnEditGroup)).click()

    def showDeleteGroupDialog(self):
        self.makeSettingsIconVisible()
        WebButton(self.waitChildControl(*MainFrame.ListGroupItem.btnDeleteGroup)).click()


class DeviceSortMode(object):
    ascending = 'ASC'
    descending = 'DESC'
    undefined = 'undefined'


class DeviceHeaderItem(object):
    def __init__(self, column, id):
        self.column = column
        self.id = id


class DeviceTableHeader(object):
    device = DeviceHeaderItem(1, 'AN')
    name = DeviceHeaderItem(2, 'MN')
    lastBackup = DeviceHeaderItem(3, 'TL')
    status = DeviceHeaderItem(4, 'T0')
    storage = DeviceHeaderItem(5, 'T3')
    clientVersion = DeviceHeaderItem(6, 'VN')
    errors = DeviceHeaderItem(7, 'T7')


class SearchFilterBy(object):
    anyField = 'ANY'
    deviceId = 'AN'
    name = 'MN'
    os = 'OS'
    version = 'VN'


class SearchFilterType(object):
    contains = 'Contains'
    equals = 'Equals'
    beginsWith = 'BeginsWith'
    endsWith = 'EndsWith'


class WebMainPage(BaseWebManagerPage):
    def __init__(self):
        super(WebMainPage, self).__init__(MainFrame.frame)
        self._buttonAllDevices = WebButton(MainFrame.btnAllDevices)
        self._buttonAddGroup = WebButton(MainFrame.btnAddGroup)
        self._groupListBuilder = WebListViewDelegateBuilder(MainFrame.ListGroupItem.listItem,
                                                         WebGroupListDelegate)
        self._groupList = WebListView(MainFrame.listGroups, self._groupListBuilder)
        self._groupDialog = GroupDialog()

        self._deviceTable = WebTableView(MainFrame.accountTable,
                                         delegateBuilder=WebTableViewDelegateBuilder(
                                             headerHandler=(WebFindKey.XPATH, "td")))

        self._searchEdit = WebLineEdit(MainFrame.txtSearch)
        self._buttonSearch = WebButton(MainFrame.btnSearch)
        self._comboBoxFilterBy = WebComboBox(MainFrame.cmbFilterBy)
        self._comboBoxFilterType = WebComboBox(MainFrame.cmbFilterType)
        self._buttonCharts = WebButton(MainFrame.btnCharts)
        self._buttonFilter = WebButton(MainFrame.btnFilter)
        self._loaderTimeoutSec = 5

    def goToHomeLocation(self):
        super(WebMainPage, self).goToHomeLocation()

    def waitForLoading(self):
        self.waitFor(lambda x: not BaseWebControl(MainFrame.formLoader).isExists(1), timeoutSec=self._loaderTimeoutSec)

    def waiter(func):
        def _decorator(self, *args, **kwargs):
            self.waitForLoading()
            return func(self, *args, **kwargs)
        return _decorator

    def isTrial(self):
        return BaseWebControl(MainFrame.trialFrame).isExists() and BaseWebControl(MainFrame.trialFrame).isVisible()

### Groups
    @waiter
    def _getGroupDelegate(self, groupName):
        items = WebListView(MainFrame.listGroups, self._groupListBuilder).itemsFor(lambda x: x.groupName() == groupName)
        return items[0] if items else None

    def editGroup(self, name, newName):
        groupDelegate = self._getGroupDelegate(name)
        groupDelegate.showEditGroupDialog()
        self.waitFor(lambda x: BaseWebControl(Dialog.anyDialog).isExists(), 3, "Edit group dialog didn't appear")
        self.waitForLoading()
        self._groupDialog.setGroupName(newName)
        self._groupDialog.save()

    @waiter
    def addGroup(self, name):
        self._buttonAddGroup.click()
        self.waitFor(lambda x: BaseWebControl(Dialog.anyDialog).isExists(), 3, "Add group dialog didn't appear")
        self.waitForLoading()
        self._groupDialog.setGroupName(name)
        self._groupDialog.save()

    def deleteGroup(self, name):
        self.selectGroupView(name)
        for i in range(self.getDeviceCount()):
            self.openDevice(0)
            DevicePage().unassignGroup()
        delegate = self._getGroupDelegate(name)
        delegate.showDeleteGroupDialog()
        self.waitForLoading()
        self._groupDialog.save()

    def selectGroupView(self, name):
        self._getGroupDelegate(name).click()

    def selectAllDeviceView(self):
        self._buttonAllDevices.click()

    @waiter
    def getGroupCount(self):
        return self._groupList.rowsCount()

    @waiter
    def getGroupList(self):
        return [item.groupName() for item in self._groupList.items()]

### View
    def viewAddGroupDialog(self):
        self.goToHomeLocation()
        self._buttonAddGroup.click()

    def viewDeleteGroupDialog(self, group=''):
        self.goToHomeLocation()
        if self._groupList.rowsCount() > 0:
            if group == '':
                self._groupList.items()[0].showEditGroupDialog()
            else:
                self._getGroupDelegate(group).showEditGroupDialog()

    def viewFilter(self):
        self.goToHomeLocation()
        self._buttonFilter.click()
        self._comboBoxFilterBy.click()

    def viewCharts(self):
        self.goToHomeLocation()
        self.waitForLoading()
        self._buttonCharts.click()

    def isChartShown(self):
        self.waitForLoading()
        return BaseWebControl(MainFrame.charts).isExists() and BaseWebControl(MainFrame.charts).isVisible()

### Devices Table
    def getSorting(self):
        return (self._deviceTable.get_attribute("data-sortmode"),
                self._deviceTable.get_attribute("data-sortcolumn"))

    @waiter
    def getDeviceCount(self):
        return len(self._deviceTable.rootDelegate().children())

    @waiter
    def getColumnItems(self, deviceHeaderItem=DeviceTableHeader.device):
        items = []
        for r in self._deviceTable.column(deviceHeaderItem.column):
            items.append(r.text)
        return items

    @waiter
    def openDevice(self, nameOrRowNumber=0):
        if isinstance(nameOrRowNumber, int):
            self._deviceTable.item(nameOrRowNumber, DeviceTableHeader.device.column).click()
        else:
            self._deviceTable.item(self.getColumnItems().index(nameOrRowNumber),
                                   DeviceTableHeader.device.column).click()

    def sortDevices(self, deviceHeaderItem, sortMode):
        currentMode, currentColumn = self.getSorting()
        if currentColumn != deviceHeaderItem.id:
            self._deviceTable.header().children()[deviceHeaderItem.column].getChildControl('xpath', './a').click()
            time.sleep(2)
        currentMode, currentColumn = self.getSorting()
        if currentMode != sortMode:
            self._deviceTable.header().children()[deviceHeaderItem.column].getChildControl('xpath', './a').click()
            time.sleep(2)

    def isColumnSorted(self, deviceHeaderItem, sortMode):
        list = self.getColumnItems(deviceHeaderItem)
        if DeviceTableHeader.storage == deviceHeaderItem:
            list = [float(x.split(' ')[0])*self._bytes(x.split(' ')[1]) for x in list]
        sortedList = sorted(list, reverse=(sortMode==DeviceSortMode.descending))
        return list==sortedList

    def _bytes(self, value):
        if value == 'B':
            return 1
        elif value == 'KB':
            return pow(10, 3)
        elif value == 'MB':
            return pow(10, 6)
        elif value == 'GB':
            return pow(10, 9)
        else:
            return 0

### Search
    def search(self, searchBy=SearchFilterBy.anyField, searchType=SearchFilterType.contains, searchText=''):
        if not self._comboBoxFilterBy.isVisible():
            self._buttonFilter.click()
        self._comboBoxFilterBy.selectItemsByDataValue(searchBy)
        self._comboBoxFilterType.selectItemsByDataValue(searchType)
        self._searchEdit.typeText(searchText)
        self._buttonSearch.click()
